package org.jdragon.springz.web.core.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.CharEncoding;
import org.apache.commons.codec.Charsets;
import org.jdragon.springz.core.annotation.Component;
import org.jdragon.springz.core.annotation.Inject;
import org.jdragon.springz.web.annotation.RequestMethod;
import org.jdragon.springz.web.core.configuration.WebConfiguration;
import org.jdragon.springz.web.core.entity.HttpRequest;
import org.jdragon.springz.web.core.entity.HttpResponse;
import org.jdragon.springz.web.core.entity.RequestParams;
import org.jdragon.springz.web.core.factory.RequestHandlerFactory;
import org.jdragon.springz.web.core.configuration.WebFilterChain;
import org.jdragon.springz.web.core.utils.UrlHelper;

import java.net.InetSocketAddress;
import java.util.Map;

/**
 * @Author: Jdragon
 * @email: 1061917196@qq.com
 * @Date: 2020.11.11 08:23
 * @Description:
 */
@Slf4j
@Component("httpServerHandler")
public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    private static final String FAVICON_ICO = "/favicon.ico";

    @Inject
    private WebConfiguration webConfiguration;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) {
        log.info("Handle http request:{}", fullHttpRequest);
        if (FAVICON_ICO.equals(fullHttpRequest.uri())) return;
        boolean keepAlive = HttpUtil.isKeepAlive(fullHttpRequest);

        InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        InetSocketAddress localAddress = (InetSocketAddress) ctx.channel().localAddress();

        String uri = fullHttpRequest.uri();
        QueryStringDecoder queryDecoder = new QueryStringDecoder(uri, Charsets.toCharset(CharEncoding.UTF_8));
        String path = queryDecoder.path();

        HttpMethod method = fullHttpRequest.method();
        RequestMethod requestMethod = RequestMethod.getRequestMethod(method);

        String matchingPath = UrlHelper.getMatchingPath(requestMethod, path);

        //空则确认不匹配
        if (matchingPath == null) {
            fullHttpRequest.retain();
            ctx.fireChannelRead(fullHttpRequest);
            return;
        }

        //封装请求参数
        String body = fullHttpRequest.content().toString(Charsets.toCharset(CharEncoding.UTF_8));
        Map<String, String> pathParams = UrlHelper.analyzePathParams(path, matchingPath);
        RequestParams requestParams = new RequestParams(
                fullHttpRequest.headers(),
                queryDecoder.parameters(),
                pathParams,
                body);

        HttpRequest httpRequest = HttpRequest.builder()
                .path(path)
                .uri(uri)
                .matchingPath(matchingPath)
                .method(requestMethod)
                .requestParams(requestParams)
                .localAddress(localAddress)
                .remoteAddress(remoteAddress)
                .build();
        HttpResponse httpResponse = new HttpResponse(ctx, keepAlive);

        WebHandler webHandler = RequestHandlerFactory.get(method);
        WebFilterChain webFilterChain = WebFilterChain.initChain(webHandler);
        webFilterChain.filter(httpRequest, httpResponse);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }


}
